package main

import (
	"context"
	"github.com/micro/cli/v2"
	"github.com/micro/go-micro/v2/auth"
	"github.com/micro/go-micro/v2/util/log"
	"github.com/micro/go-micro/v2/web"
	"github.com/morphyguo/demo/commons"
	"github.com/morphyguo/demo/web/auth/config"
	"github.com/morphyguo/demo/web/auth/initialize"
	"github.com/morphyguo/demo/web/auth/pkg/logger"
	"net/http"
	"os"

	// 引入swagger
	_ "github.com/morphyguo/demo/web/auth/pkg/swagger"
)

var (
	// Name of the authapi web
	// Address is the authapi web address
	Address = ":8012"
)

// Run the micro authapi api
func main() {
	//s:= web.NewService(web.Name(commons.NsWebAdmin), web.Address(Address))
	//app:= gin.Default()
	//app.Static("/", "html")
	//
	//s.Handle("/",app)
	//s.Init()
	//s.Run()

	service := web.NewService(
		web.Name(commons.NsWebAdmin),
		web.Address(Address),
		web.Flags(&cli.StringFlag{
			Name:     "conf",
			Aliases:  []string{"c"},
			Usage:    "配置文件(.json,.yaml,.toml)",
			Required: true,
		},
			&cli.StringFlag{
				Name:     "model",
				Aliases:  []string{"m"},
				Usage:    "casbin的访问控制模型(.conf)",
				Required: true,
			},
			&cli.StringFlag{
				Name:  "menu",
				Usage: "初始化菜单数据配置文件(.yaml)",
			},
			&cli.StringFlag{
				Name:  "www",
				Usage: "静态站点目录",
			}),
	)

	opts := []Option{}
	service.Init(web.Action(func(c *cli.Context) {
		opts = append(opts, SetConfigFile(c.String("conf")))
		opts = append(opts, SetModelFile(c.String("model")))
		opts = append(opts, SetMenuFile(c.String("menu")))
		opts = append(opts, SetWWWDir(c.String("www")))
	}),)

	h := handler{
		auth: service.Options().Service.Options().Auth,
	}

	if h.auth.Options().Provider == nil {
		log.Fatal("Auth provider is not set")
	}

	if router,err := initHandler(context.Background(), opts...);err != nil {
		log.Fatal("error exit",err)
	} else {
		service.Handle("/", router)
	}

	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

func initHandler(ctx context.Context, opts ...Option) (http.Handler,error) {
	var o options
	for _, opt := range opts {
		opt(&o)
	}

	config.MustLoad(o.ConfigFile)
	if v := o.ModelFile; v != "" {
		config.C.Casbin.Model = v
	}
	if v := o.WWWDir; v != "" {
		config.C.WWW = v
	}
	if v := o.MenuFile; v != "" {
		config.C.Menu.Data = v
	}

	logger.Printf(ctx, "服务启动，运行模式：%s，版本号：%s，进程号：%d", config.C.RunMode, o.Version, os.Getpid())

	// 初始化日志模块
	_, err := initialize.InitLogger()
	if err != nil {
		return nil,err
	}

	// 初始化图形验证码
	initialize.InitCaptcha()

	// 初始化依赖注入器
	injector, _, err := initialize.BuildInjector()
	if err != nil {
		return nil,err
	}

	// 初始化菜单数据
	err = injector.Menu.Load()
	if err != nil {
		return nil,err
	}

	// 初始化HTTP服务
	return injector.Engine,nil

}

type handler struct {
	auth auth.Auth
}
type options struct {
	ConfigFile string
	ModelFile  string
	MenuFile   string
	WWWDir     string
	Version    string
}

// Option 定义配置项
type Option func(*options)

// SetConfigFile 设定配置文件
func SetConfigFile(s string) Option {
	return func(o *options) {
		o.ConfigFile = s
	}
}

// SetModelFile 设定casbin模型配置文件
func SetModelFile(s string) Option {
	return func(o *options) {
		o.ModelFile = s
	}
}

// SetWWWDir 设定静态站点目录
func SetWWWDir(s string) Option {
	return func(o *options) {
		o.WWWDir = s
	}
}

// SetMenuFile 设定菜单数据文件
func SetMenuFile(s string) Option {
	return func(o *options) {
		o.MenuFile = s
	}
}

// SetVersion 设定版本号
func SetVersion(s string) Option {
	return func(o *options) {
		o.Version = s
	}
}
